﻿namespace SecutityLib
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// Rail fence class
    /// </summary>
    public class RailFence : EncodingDecodingTech
    {
        /// <summary>
        /// Encodes the specified plain text.
        /// </summary>
        /// <param name="plainText">The plain text.</param>
        /// <param name="key">The key.</param>
        /// <returns>
        /// cipher text
        /// </returns>
        public override string Encode(string plainText, string key)
        {
            this.CheckText(plainText);

            int intkey;
            try
            {
                intkey = int.Parse(key);
            }
            catch
            {
                throw new System.Exception("Invalid Key (Must be an integer)");
            }

            string[] tempCipher = new string[intkey];
            for (int i = 0; i < intkey; i++)
            {
                tempCipher[i] = string.Empty;
            }

            int cipherInd = 0;

            for (int i = 0; i < plainText.Length; i++)
            {
                tempCipher[cipherInd] += plainText[i];
                cipherInd++;
                cipherInd %= intkey;
            }

            string cipher = string.Empty;

            for (int i = 0; i < intkey; i++)
            {
                cipher += tempCipher[i];
            }

            return cipher;
        }

        /// <summary>
        /// Decodes the specified plain text.
        /// </summary>
        /// <param name="cipherText">the cipher text</param>
        /// <param name="key">The key.</param>
        /// <returns>
        /// cipher text
        /// </returns>
        public override string Decode(string cipherText, string key)
        {
            this.CheckText(cipherText);

            int intkey;
            try
            {
                intkey = int.Parse(key);
            }
            catch
            {
                throw new System.Exception("Invalid Key (Must be an integer)");
            }

            int numberofCol = cipherText.Length / intkey;
            while (cipherText.Length % intkey != 0)
            {
                cipherText += 'x';
                numberofCol = cipherText.Length / intkey;
            }

            string[] tempPlain = new string[intkey];

            for (int i = 0; i < intkey; i++)
            {
                tempPlain[i] = string.Empty;
            }

            int plainInd = 0;

            for (int i = 0; i < cipherText.Length; i++)
            {
                tempPlain[plainInd] += cipherText[i];
                if ((i + 1) % numberofCol == 0)
                {
                    plainInd++;
                }
            }

            string plain = string.Empty;

            for (int i = 0; i < numberofCol; i++)
            {
                for (int j = 0; j < intkey; j++)
                {
                    plain += tempPlain[j][i];
                }
            }

            return plain;
        }

        /// <summary>
        /// Checks the text.
        /// </summary>
        /// <param name="text">The text.</param>
        private void CheckText(string text)
        {
            for (int i = 0; i < text.Length; i++)
            {
                if (text[i] < 'a' || text[i] > 'z')
                {
                    throw new Exception("Text must be char");
                }
            }
        }
    }
}
